/*
*    Phantom v2.0 GUI Automation Software
*    Copyright (C) 2009  John C. Van Arsdall (john@phantomtest.com)
*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License along
*    with this program; if not, write to the Free Software Foundation, Inc.,
*    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
// Operator.cpp: implementation of the COperator class.
//
//////////////////////////////////////////////////////////////////////

#include "ssi_operator.h"
#include "ssi_operator.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

COperator::COperator()
: Mode(0)
{
  Type = 0;
}

COperator::~COperator()
{

}

void COperator::SetType(SSI_INT64 NewType)
{
  Type = NewType;
}

void COperator::ClearType()
{
  Type = SSI_NULL;
}

SSI_BOOL COperator::TestForOperator(const String& Input)
{
  SSI_BOOL bRet = 0;
  if(Input.GetLength() > 2) return 0;
  if(Input.GetLength() <= 0) return 0;

  if(StrToType(String(Input.SubString(0, 0))))
  {
    bRet = 1;
  }
  if(!bRet) return 0;

  if(Input.GetLength() > 1)
  {
    if(StrToType(String(Input.SubString(1, 1))))
    {
      bRet = 1;
    }
  }
  return bRet;
}


// Deprecated
SSI_BYTE COperator::GetMode(const String& Input)
{
	SSI_BYTE Ret = 0;
  SSI_CHAR C;
  
  if(Input.GetLength() != 1) return 0;
  
  C = Input[0];
	// Active Modes alter the left hand side
	// Passive Modes do not alter any of the variables
  switch (C)
  {
		case EQUAL_OP:    Ret = OP_MODE_ACTIVE;    break;
		default:          Ret = OP_MODE_PASSIVE;
	}
	return Ret;
}


SSI_INT64 COperator::StrToType(const String& Input)
{
  SSI_INT64 Ret = 0;
  SSI_CHAR C;
  
  if(Input.GetLength() != 1) return 0;
  
  C = Input[0];
  switch (C)
  {
  case EQUAL_OP:    Ret = oEQUAL;    break;
  case GREATER_OP:  Ret = oGREATER;  break;
  case LESS_OP:     Ret = oLESS;     break;
  case NOT_OP:      Ret = oNOT;      break;
  
  case PLUS_OP:     Ret = oPLUS;     break;
  case MINUS_OP:    Ret = oMINUS;    break;
  case DIVIDE_OP:   Ret = oDIVIDE;   break;
  case MULTIPLY_OP: Ret = oMULTIPLY; break;
  case POWER_OP:    Ret = oPOWER;    break;
  case MODULOUS_OP: Ret = oMODULOUS; break;
	case DOT_OP:      Ret = oDOT;      break;
  case AND_OP:      Ret = oBIT_AND;  break;
  case OR_OP:       Ret = oBIT_OR;   break;
  default:          Ret = 0;
  }
  return Ret;
}

String COperator::TypeToStr(SSI_INT64 In)
{
  String Ret;

	switch (In)
  {
	case oEQUAL:    Ret.Format("%c", EQUAL_OP);    break;
  case oGREATER:  Ret.Format("%c", GREATER_OP);  break;
  case oLESS:     Ret.Format("%c", LESS_OP);     break;
  case oNOT:      Ret.Format("%c", NOT_OP);      break;
  
  case oPLUS:     Ret.Format("%c", PLUS_OP);     break;
  case oMINUS:    Ret.Format("%c", MINUS_OP);    break;
  case oDIVIDE:   Ret.Format("%c", DIVIDE_OP);   break;
  case oMULTIPLY: Ret.Format("%c", MULTIPLY_OP); break;
  case oPOWER:    Ret.Format("%c", POWER_OP);    break;
  case oMODULOUS: Ret.Format("%c", MODULOUS_OP); break;
	case oDOT:      Ret.Format("%c", DOT_OP); break;
  case oBIT_AND:  Ret.Format("%c", AND_OP); break;
  case oBIT_OR:   Ret.Format("%c", OR_OP); break;
	default:        Ret = "Error";
  }
  return Ret;
}


CStatus COperator::SetLeft(CVariable &Var)
{
  Left_Var = Var;
  return STAT_OK;
}

CStatus COperator::SetRight(CVariable &Var)
{
  Right_Var = Var;
  return STAT_OK;
}

CVariable COperator::GetLeft()
{
  return Left_Var;
}

CVariable COperator::GetRight()
{
  return Right_Var;
}

/*
CStatus COperator::Evaluate()
{
  // Need to re-do this.  Perhaps tie it to the Engine??
  if(Type == oEQUAL)
  {
    if(CVariable::CheckCompatibility(Left_Var.Type, Right_Var.Type))
    {
      Left_Var << Right_Var;
      return STAT_SUCCESS;
    }
    else
    {
      return STAT_FAIL;
    }
  }
  return STAT_FAIL;
}
*/

COperator& COperator::operator =(COperator &Other)
{
  Left_Var = Other.Left_Var;
  Right_Var = Other.Right_Var;
  Type = Other.Type;
  return *this;
}

// Deprecated
void COperator::SetMode(SSI_BYTE NewMode)
{
	Mode |= NewMode;
}

CStatus COperator::AddType(SSI_INT64 NewType)
{
	if(!NewType){
		// Unrecognized operator type
    MAKEERR0(ERR02029);
	}

	switch(Type)
	{
		case(oPLUS):
			{
				if(NewType == oPLUS){
					Type = oINCREMENT;
				}else{
					MAKEERR2(ERR03326, COperator::TypeToStr(oPLUS).Str(), COperator::TypeToStr(NewType).Str());
				}
				break;
			}
		case(oMINUS):
			if(NewType == oMINUS){
				Type = oDECREMENT;
			}else{
				MAKEERR2(ERR03327, COperator::TypeToStr(oMINUS).Str(), COperator::TypeToStr(NewType).Str());
			}
			break;
		case(oEQUAL):
			switch(NewType)
			{
				case(oGREATER):
					Type = Type | oGREATER; break;
				case(oLESS):	
					Type = Type | oLESS; break;
				case(oNOT):	
					Type = oNOT_EQUAL; break;
				case(oEQUAL):	
					Type = oEQUAL_EQUAL; break;
				default: {
									MAKEERR1(ERR03328, COperator::TypeToStr(NewType).Str());
								 }
			}
			break;
		case(oBIT_AND):
			if(NewType == oBIT_AND){
				Type = oLOG_AND;
			}else{
				MAKEERR1(ERR03339, COperator::TypeToStr(NewType).Str());
			}
			break;
		case(oBIT_OR):
			if(NewType == oBIT_OR){
				Type = oLOG_OR;
			}else{
				MAKEERR1(ERR03340, COperator::TypeToStr(NewType).Str());
			}
			break;
		case(oNOT):
			switch(NewType)
			{
				case(oEQUAL):	
					Type = oNOT_EQUAL; break;
				default: {
									MAKEERR1(ERR03329, COperator::TypeToStr(NewType).Str());
								 }
			}
			break;
		case(oGREATER):
			switch(NewType)
			{
				case(oEQUAL):	
					Type = Type | NewType; break;
				default: {
									MAKEERR1(ERR03330, COperator::TypeToStr(NewType).Str());
								 }
			}
			break;
		case(oLESS):
			switch(NewType)
			{
				case(oEQUAL):	
					Type = Type | NewType; break;
				default: {
									MAKEERR1(ERR03331, COperator::TypeToStr(NewType).Str());
								 }
			}
			break;
		default: {
							MAKEERR1(ERR03332, COperator::TypeToStr(NewType).Str());
						 }
	}

	return STAT_OK;
}



